package instan_srv

import (
	"encoding/json"
	"fmt"
	"gluenet/pkg/agent/types"
	apis2 "gluenet/pkg/apis"
	"gluenet/pkg/meta"
	glue2 "gluenet/pkg/platform/glue"
	"strings"

	"gopkg.in/yaml.v3"
)

func ProxyServiceGet(ctx *apis2.GlueContext) {
	var (
		err     error
		guid    string
		service string
		url     string
	)
	guid = ctx.WebContext.URLParam("guid")
	service = ctx.WebContext.URLParam("service")
	url = ctx.WebContext.URLParam("url")

	ctx.Logger.Debugf("guid: %v,url: %v, service %v", guid, service, url)

	urlPrefix, err := getServiceUrlPrefix(ctx, guid, service)
	if err != nil {
		ctx.Logger.Debugf("get url %v", err)
		ctx.WebContext.JSON(apis2.ResponseOK(nil))
		return
	}

	var res *meta.ScheduleResults
	if err = ctx.DataBase.ScheduleResultGet(guid, &res); err != nil {
		ctx.Logger.Errorf("find the agent guid %v", err)
		ctx.WebContext.JSON(apis2.ResponseReqErr(fmt.Errorf("find the agent guid %v", err), nil))
		return
	}

	sMaps, err := meta.DeCodeScheduleMaps(res.ScheduleMap)
	if err != nil {
		ctx.Logger.Errorf("decode schedule map %v", err)
		ctx.WebContext.JSON(apis2.ResponseReqErr(fmt.Errorf("decode schedule map %v", err), nil))
		return
	}

	var req = types.ProxyGet{
		HttpUrl: urlPrefix + url,
	}
	bts, _ := json.Marshal(req)
	resp, err := ctx.Rpc.Request(strings.Join([]string{sMaps[service], apis2.RPCHttpProxyGet}, ":"), bts)
	if err != nil {
		ctx.Logger.Errorf("send proxy request %v", err)
		ctx.WebContext.JSON(apis2.ResponseReqErr(fmt.Errorf("send proxy request %v", err), nil))
		return
	}

	//fmt.Printf("\n\n %s \n\n", resp)
	var proxyResp = types.HttpProxyResp{}
	json.Unmarshal(resp, &proxyResp)

	//fmt.Printf("\n\n %s \n\n", proxyResp.Data)

	if proxyResp.IsSuccess {
		ctx.WebContext.JSON(apis2.ResponseOK(fmt.Sprintf("%s", proxyResp.Data)))
	} else {
		ctx.Logger.Errorf("proxy request %v", proxyResp.Message)
		ctx.WebContext.JSON(apis2.ResponseReqErr(fmt.Errorf("proxy request %v", proxyResp.Message), nil))
		return
	}
}

func getServiceUrlPrefix(ctx *apis2.GlueContext, guid string, service string) (string, error) {
	//var ins []meta.Instance
	//if err := orm.InstanceGet(ctx.DataBase, guid, &ins); err != nil || len(ins) == 0 {
	//	return "", fmt.Errorf("guid not exist", err)
	//}
	var ins *meta.Instance
	if err := ctx.DataBase.InstanceGet(guid, &ins); err != nil {
		return "", fmt.Errorf("get instance %v", err)
	}

	labels := strings.Split(ins.Label, ".")
	if labels[1] != apis2.ModuleDefault || labels[3] != apis2.KindApplication {
		return "", fmt.Errorf("instance must running on gluenets and must be application")
	}

	var instance glue2.Instance
	if err := json.Unmarshal([]byte(ins.InstanceValue), &instance); err != nil {
		return "", fmt.Errorf("decode instance value error", err)
	}

	var containers glue2.Containers
	if err := yaml.Unmarshal([]byte(instance.InstanceYaml), &containers); err != nil {
		return "", fmt.Errorf("decode instance yaml value error", err)
	}

	url, ok := containers.Containers[service]
	if !ok {
		return "", fmt.Errorf("instance not exist service %v", service)
	}

	if url.ReportProxyServicPerfix == "" {
		return "", fmt.Errorf("instance must offer service, declare in instance_yaml.servic_perfix")
	}

	return url.ReportProxyServicPerfix, nil
}
